﻿using Avalonia.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using P2P.Client.Model;
using P2P.Client.Buffer;
using P2P.Client.Tasks;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json.Nodes;
using System.Threading.Tasks;
using P2P.Client.Enums;
using P2P.Network.ExtensionMethods;

namespace P2P.Client.Handler
{
    public class UserHandler
    {
        private ApiProtocol apiProtocol;

        public UserHandler(ApiProtocol apiProtocol)
        {
            this.apiProtocol = apiProtocol;
        }

        private TimerTask heartbeatTaskMain;
        private TimerTask heartbeatTaskTurn;

        public void LoginAck() 
        {
            bool success = false;
            bool.TryParse(apiProtocol.Params["Success"].ToString(),out success);

            if (success)
            {
                Hosts hosts = JsonConvert.DeserializeObject<Hosts>(apiProtocol.Params["Hosts"].ToString());


                SharedModel.Instance.MainServerInfo.ConnectStatus = ConnectStatus.Connected;
                string accountId = apiProtocol.Params["AccountId"].ToString();

                SharedModel.Instance.Configure(accountId,hosts);

                heartbeatTaskMain = new TimerTask(() =>
                {
                    if (SharedModel.Instance.MainServerInfo.ConnectStatus == ConnectStatus.Disconnected) 
                    {
                        heartbeatTaskMain.Dispose();
                        return;
                    }

                    JObject data = new JObject();
                    data.Add("Name", "ClientHeartbeat");
                    data.Add("Method", "ClientHeartbeat");
                    data.Add("Version", "1.0");

                    JObject param = new JObject();
                    param.Add("AccountId", SharedModel.Instance.AccountId);
                    data.Add("Params", param);
                    string ack = JsonConvert.SerializeObject(R<JObject>.Ok(data));
                    apiProtocol.Socket.SendTo(ack, apiProtocol.RemoteEndPoint);
                }, TimeSpan.FromSeconds(5));

                {
                    JObject turnData = new JObject();
                    turnData.Add("Name", "TurnLogin");
                    turnData.Add("Method", "TurnLogin");
                    turnData.Add("Version", "1.0");

                    JObject turnParam = new JObject();
                    turnParam.Add("AccountId", SharedModel.Instance.AccountId);
                    turnData.Add("Params", turnParam);

                    string req = JsonConvert.SerializeObject(R<JObject>.Ok(turnData));

                    SharedModel.Instance.UDPSocketListener.SendTo(req,
                        SharedModel.Instance.Hosts.UDPTurnServerIP,
                        SharedModel.Instance.Hosts.UDPTurnServerPort.Value);

                    SharedModel.Instance.TurnServerInfo.ConnectStatus = ConnectStatus.Connecting;
                }
                

                JObject data = new JObject();
                data.Add("Name", "NatCheck");
                data.Add("Method", "Step1");
                data.Add("Version", "1.0");
                JObject param = new JObject();
                param.Add("AccountId", SharedModel.Instance.AccountId);
                data.Add("Params", param);
                string ack = JsonConvert.SerializeObject(R<JObject>.Ok(data));
                apiProtocol.Socket.SendTo(ack, SharedModel.Instance.Hosts.UDPStunServerIP,
                    SharedModel.Instance.Hosts.UDPStunServerPort.Value);
            }
            else 
            {
                LogBuffer.Instance().Buffer.Enqueue(new LogModel() { Log = apiProtocol.Params.ToString(),Time = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") });
            }
        }


        public void TurnLoginAck() 
        {
            bool success = false;
            bool.TryParse(apiProtocol.Params["Success"].ToString(), out success);

            if (success)
            {
                SharedModel.Instance.TurnServerInfo.ConnectStatus = ConnectStatus.Connected;

                heartbeatTaskTurn = new TimerTask(() =>
                {
                    if (SharedModel.Instance.TurnServerInfo.ConnectStatus == ConnectStatus.Disconnected)
                    {
                        heartbeatTaskTurn.Dispose();
                        return;
                    }

                    JObject data = new JObject();
                    data.Add("Name", "TurnClientHeartbeat");
                    data.Add("Method", "TurnClientHeartbeat");
                    data.Add("Version", "1.0");

                    JObject param = new JObject();
                    param.Add("AccountId", SharedModel.Instance.AccountId);
                    data.Add("Params", param);
                    string ack = JsonConvert.SerializeObject(R<JObject>.Ok(data));
                    apiProtocol.Socket.SendTo(ack, SharedModel.Instance.Hosts.UDPTurnServerIP,
                        SharedModel.Instance.Hosts.UDPTurnServerPort.Value);
                }, TimeSpan.FromSeconds(5));
            }
        }
    }
}
